/*
Simple Forum Auto Poster.
Copyright (C) 2011 Gianni Van Hoecke.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package domain.net;

import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML.Attribute;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.parser.ParserDelegator;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

/**
 *
 * @author Gianni Van Hoecke <gianni.vh@gmail.com>
 *
 * This class is used for analyzing a HTML page.
 */
public class HTMLParser
{
    /**
     * Extract the value of the a tag.<br />
     * <b>Example:</b><br />
     * String s = "&lt;input type=\"text\" size=\"50\" id=\"imagecode1\" value=\"text in inputbox\" /&gt;";<br />
     * HTMLParser.extractValueFromTag(new StringReader(s), Tag.INPUT, Attribute.ID, "imagecode1", Attribute.VALUE);<br />
     * Would return (first index) "text in inputbox".
     * @param html A reader that contains the HTML.
     * @param beginTag The tag to look for.
     * @param matchA The attribute to look for.
     * @param matchS The value the attributes must match.
     * @param value The attribute value that must be stored.
     * @return A list of all values.
     * @throws Exception On error.
     */
    public static List<String> extractValueFromTag(Reader html, final Tag beginTag, final Attribute matchA, final String matchS, final Attribute value) throws Exception
    {
        final ArrayList<String> list = new ArrayList<String>();
        
        ParserDelegator parserDelegator = new ParserDelegator();
        ParserCallback parserCallback = new ParserCallback()
        {

            @Override
            public void handleText(final char[] data, final int pos)
            {
            }

            @Override
            public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos)
            {
            }

            @Override
            public void handleEndTag(Tag t, final int pos)
            {
            }

            @Override
            public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, final int pos)
            {
                try
                {
                    if (tag == beginTag)
                    {
                        String att = (String)attribute.getAttribute(matchA);
                        if(att.toLowerCase().equals(matchS.toLowerCase()))
                        {
                            list.add((String)attribute.getAttribute(value));
                        }
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleComment(final char[] data, final int pos)
            {
            }

            @Override
            public void handleError(final java.lang.String errMsg, final int pos)
            {
            }
        };
        
        parserDelegator.parse(html, parserCallback, true);
        return list;
    }

    /**
     * Gets all HREFs.
     * @param html A reader that contains the HTML.
     * @return A list of all extracted values.
     * @throws Exception On error.
     */
    public static List<String> getHREF(Reader html) throws Exception
    {
        final ArrayList<String> list = new ArrayList<String>();

        ParserDelegator parserDelegator = new ParserDelegator();
        ParserCallback parserCallback = new ParserCallback()
        {

            @Override
            public void handleText(final char[] data, final int pos)
            {
            }

            @Override
            public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos)
            {
                try
                {
                    if (tag == Tag.A)
                    {
                        list.add((String)attribute.getAttribute(Attribute.HREF));
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleEndTag(Tag t, final int pos)
            {
            }

            @Override
            public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, final int pos)
            {
            }

            @Override
            public void handleComment(final char[] data, final int pos)
            {
            }

            @Override
            public void handleError(final java.lang.String errMsg, final int pos)
            {
            }
        };

        parserDelegator.parse(html, parserCallback, true);
        return list;
    }

    /**
     * Gets all IMG sources.
     * @param html A reader that contains the HTML.
     * @return A list of all extracted "src" values.
     * @throws Exception On error.
     */
    public static List<String> getSRC(Reader html) throws Exception
    {
        final ArrayList<String> list = new ArrayList<String>();

        ParserDelegator parserDelegator = new ParserDelegator();
        ParserCallback parserCallback = new ParserCallback()
        {

            @Override
            public void handleText(final char[] data, final int pos)
            {
            }

            @Override
            public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos)
            {
                try
                {
                    String src = (String)attribute.getAttribute(Attribute.SRC);
                    if(src != null)
                    {
                        list.add(src);
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleEndTag(Tag t, final int pos)
            {
            }

            @Override
            public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, final int pos)
            {
                try
                {
                    String src = (String)attribute.getAttribute(Attribute.SRC);
                    if(src != null)
                    {
                        list.add(src);
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleComment(final char[] data, final int pos)
            {
            }

            @Override
            public void handleError(final java.lang.String errMsg, final int pos)
            {
            }
        };

        parserDelegator.parse(html, parserCallback, true);
        return list;
    }

    /**
     * Gets all input and textarea tags.
     * @param html A reader that contains the HTML.
     * @return A list of NameValuePair.
     * @throws Exception On error.
     */
    public static List<NameValuePair> getFormInputs(Reader html) throws Exception
    {
        final List<NameValuePair> list = new ArrayList<NameValuePair>();

        ParserDelegator parserDelegator = new ParserDelegator();
        ParserCallback parserCallback = new ParserCallback()
        {

            @Override
            public void handleText(final char[] data, final int pos)
            {
            }

            @Override
            public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos)
            {
                try
                {
                    if(tag == Tag.TEXTAREA)
                    {
                        String tagName = (String)attribute.getAttribute(Attribute.NAME);
                        String tagValue = "";
                        list.add(new BasicNameValuePair(tagName, tagValue));
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleEndTag(Tag t, final int pos)
            {
            }

            @Override
            public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, final int pos)
            {
                try
                {
                    if (tag == Tag.INPUT)
                    {
                        String tagName = (String)attribute.getAttribute(Attribute.NAME);
                        String tagType = (String)attribute.getAttribute(Attribute.TYPE);
                        
                        if(tagName == null || tagName.equals(""))
                            if(!tagType.toLowerCase().trim().equals("submit"))
                                tagName = tagType;
                        
                        String tagValue = (String)attribute.getAttribute(Attribute.VALUE);
                        list.add(new BasicNameValuePair(tagName, tagValue));
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleComment(final char[] data, final int pos)
            {
            }

            @Override
            public void handleError(final java.lang.String errMsg, final int pos)
            {
            }
        };

        parserDelegator.parse(html, parserCallback, true);
        return list;
    }

    /**
     * Gets all content from all textareas.
     * @param html A reader that contains the HTML.
     * @return A list of NameValuePair.
     * @throws Exception On error.
     */
    public static List<NameValuePair> getTextAreaContent(Reader html) throws Exception
    {
        final List<NameValuePair> list = new ArrayList<NameValuePair>();

        ParserDelegator parserDelegator = new ParserDelegator();
        ParserCallback parserCallback = new ParserCallback()
        {
            boolean ok = false;

            @Override
            public void handleText(final char[] data, final int pos)
            {
                if(ok)
                    list.add(new BasicNameValuePair("TEXTAREA", new String(data)));
            }

            @Override
            public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos)
            {
                try
                {
                    if(tag == Tag.TEXTAREA)
                    {
                        ok = true;
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleEndTag(Tag t, final int pos)
            {
                try
                {
                    if(t == Tag.TEXTAREA)
                    {
                        ok = false;
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, final int pos)
            {
            }

            @Override
            public void handleComment(final char[] data, final int pos)
            {
            }

            @Override
            public void handleError(final java.lang.String errMsg, final int pos)
            {
            }
        };

        parserDelegator.parse(html, parserCallback, true);
        return list;
    }

    /**
     * Gets all content from all textareas.
     * @param html A reader that contains the HTML.
     * @return A list of NameValuePair.
     * @throws Exception On error.
     */
    public static List<NameValuePair> getTextAreaContentFrom(Reader html, final Attribute att, final String value) throws Exception
    {
        final List<NameValuePair> list = new ArrayList<NameValuePair>();

        ParserDelegator parserDelegator = new ParserDelegator();
        ParserCallback parserCallback = new ParserCallback()
        {
            boolean ok = false;

            @Override
            public void handleText(final char[] data, final int pos)
            {
                if(ok)
                    list.add(new BasicNameValuePair("TEXTAREA", new String(data)));
            }

            @Override
            public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos)
            {
                try
                {
                    if(tag == Tag.TEXTAREA)
                    {
                        String att_value = (String)attribute.getAttribute(att);
                        if(att_value.toLowerCase().equals(value))
                            ok = true;
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleEndTag(Tag t, final int pos)
            {
                try
                {
                    if(t == Tag.TEXTAREA)
                    {
                        ok = false;
                    }
                }catch(Exception e){/*Ignore*/}
            }

            @Override
            public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, final int pos)
            {
            }

            @Override
            public void handleComment(final char[] data, final int pos)
            {
            }

            @Override
            public void handleError(final java.lang.String errMsg, final int pos)
            {
            }
        };

        parserDelegator.parse(html, parserCallback, true);
        return list;
    }
}